package com.lzyyj.gmis.base.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lzyyj.common.GenericsUtils;
import com.lzyyj.common.Page;
import com.lzyyj.gmis.base.dao.IBaseDao;
import com.lzyyj.gmis.base.dao.PersistenceHelper;

public class BaseService<T, PK extends Serializable> implements IBaseService<T, PK>,Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1627171223163709523L;
	
	private static final Log log = LogFactory.getLog(BaseService.class);
	
	private Class<T> entityClass;

	private ISystemService systemService;
	
	@Override
	public ISystemService getSystemService() {
		return systemService;
	}

	@Override
	public void setSystemService(ISystemService systemService) {
		this.systemService = systemService;
	}
	
	@Override
	public <T1, PK1 extends Serializable> IBaseService<T1, PK1> getBaseService(Class<T1> clazz1) {
		IBaseService<T1, PK1> baseService = null;
		
		if (serviceMap.containsKey(clazz1)){
			baseService = (IBaseService<T1, PK1>)serviceMap.get(clazz1);
		}
		
		return baseService;
	}

	/**
	 * 接驳旧的业务服务代码
	 */
	private Object oldService;
	
	public Object getOldService() {
		return oldService;
	}

	public void setOldService(Object oldService) {
		this.oldService = oldService;
	}

	private static Map<Class<?>, IBaseService<?, Serializable>> serviceMap = new HashMap<Class<?>, IBaseService<?,Serializable>>();
	
	private static int createCount = 0;
		
	protected String moduleId = ""+serialVersionUID;
	
	public String getModuleId() {
		return moduleId;
	}

	public void setModuleId(String moduleId) {
		this.moduleId = moduleId;
	}

	protected String moduleName;
	
	public String getModuleName() {
		if (moduleName==null){
			moduleName="基本功能模块"+moduleId;
		}
		return moduleName;
	}

	public void setModuleName(String moduleName) {
		this.moduleName = moduleName;
	}
	
	private IBaseDao<T, PK> baseDao;;

	public IBaseDao<T, PK> getBaseDao() {
		return baseDao;
	}

	public void setBaseDao(IBaseDao<T, PK> baseDao) {
		this.baseDao = baseDao;
	}

	public IBaseDao<T, PK> useBaseDao() throws Exception {
		if (baseDao==null){
			throw new Exception("部署错误：没有配置 数据库访问 Dao");
		}
		return baseDao;
	}

	/**
	 * 本服务要用到的Dao列表
	 */
	private Map<String, IBaseDao<?, ?>> daoMap = new HashMap<String, IBaseDao<?, ?>>();

	public Map<String, IBaseDao<?, ?>> getDaoMap() {
		return daoMap;
	}

	public void setDaoMap(Map<String, IBaseDao<?, ?>> daoMap) {
		this.daoMap = daoMap;
	}

	protected <E, PK1 extends Serializable> IBaseDao<E, PK1> getDao(Class<IBaseDao<E, PK1>> clazz) {
		IBaseDao<E, PK1> retDao = null;
		
		if (clazz!=null&&daoMap.containsKey(clazz.getSimpleName())){
			retDao = (IBaseDao<E, PK1>)daoMap.get(clazz.getSimpleName());
		}
		
		return retDao;
	}
	
	/**
	 * 获取管理的实体类
	 */
	@Override
	public Class<T> getEntityClass() {
		Class<T> clazz = null;
		
		if (getBaseDao()!=null){
			clazz = getBaseDao().getEntityClass();
		}
		
		return clazz;
	}
	
	protected static String[] properties = null;
	
	public String[] getProperties() throws Exception {
		if (properties==null){
			if (getBaseDao()!=null){
				properties = useBaseDao().getProperties();
			}else{
				
			}
		}
		return properties;
	}

	public static void setProperties(String[] properties) {
		BaseService.properties = properties;
	}

	protected static Map<String, Object> propertyMap = null;

	public Map<String, Object> getPropertyMap() throws Exception {
		if (propertyMap==null){
			propertyMap = new HashMap<String, Object>();
			for (String property:getProperties()){
				propertyMap.put(property, property);
			}
		}
		return propertyMap;
	}

	public void setPropertyMap(Map<String, Object> value) {
		propertyMap = value;
	}

	@SuppressWarnings("unchecked")
	private void parseEntityClass(Class<T> entityClass) {
		String description;
		if (entityClass==null){
			this.entityClass = (Class<T>)GenericsUtils.getSuperClassGenricType(getClass(), BaseService.class, "T");
			description = "默认构造";
		}else{
			this.entityClass = entityClass;
			description = "带参构造";
		}
		Class<PK> pkClass = (Class<PK>)GenericsUtils.getSuperClassGenricType(getClass(), BaseService.class, 1);
		log.debug(getClass().getSimpleName()+" "+description+"("+(++createCount)+")，"+" 管理实体: "+this.entityClass+" 主键："+pkClass+" ， moduleId："+moduleId+" moduleName:"+ moduleName +"");
	}
	
	public BaseService() {
		parseEntityClass(null);
	}
	
	public BaseService(Class<T> entityClass) {
		parseEntityClass(entityClass);
	}

	@Override
	public T getNew() throws Exception{
		return useBaseDao().getNew();
	}

	@Override
	public T getNew(T example, String propertyList) throws Exception {
		T entity = getNew();
		copyProperties(example, entity, propertyList, false);
		return entity;
	}

	/**
	 * 属性复制
	 * @param sourceVo
	 * @param targetPo
	 * @param copyPropertyList
	 * @param persistent 针对外键引用，是否需要进行持久化转换
	 * @throws Exception 
	 */
	@SuppressWarnings("unchecked")
	public <F, F1> Map<String, String> copyProperties(F sourceVo, F targetPo, String copyPropertyList, boolean persistent) throws Exception {
		return PersistenceHelper.copyProperties(sourceVo, targetPo, copyPropertyList, persistent, (IBaseDao<F, PK>)useBaseDao());
	}

	/**
	 * 获得实体类属性列表
	 * @return
	 * @throws Exception 
	 */
	@Override
	public String getPropertyList() throws Exception {
		return useBaseDao().getPropertyList();
	}

	@Override
	public T get(PK id) throws Exception {
		return useBaseDao().getById(id);
	}

	@Override
	public T get(T instance) throws Exception{
		return get(instance, null);
	}

	@Override
	public T get(T entity, String propertyList) throws Exception{
		T po = useBaseDao().get(entity, propertyList);
		return po;
	}

	@Override
	public T getForModify(PK id) throws Exception {
		T entityPo = useBaseDao().getById(id);
		return entityPo;
	}

	@Override
	public T getForModify(T entity) throws Exception {
		return getForModify(entity, null);
	}
	
	@Override
	public T getForModify(T instance, String propertyList) throws Exception {
		T entityPo = get(instance, propertyList);
		return entityPo;
	}
	
	@Override
	public Map<Class<?>, Map<Serializable, Object>> loadProperties(T entityPo, String propertyList, Map<Class<?>, Map<Serializable, Object>> propertyValueCache) throws Exception{
		return useBaseDao().loadProperties(entityPo, entityClass, propertyList, propertyValueCache);
	}

	@Override
	public void del(PK id) throws Exception {
		T entityPo = useBaseDao().getById(id);
		if (entityPo == null) {
			throw new Exception("参数无效！");
		}
		useBaseDao().deleteById(id);
	}

	@Override
	public void del(PK[] ids) throws Exception {
		for (PK id : ids) {
			this.del(id);
		}
	}

	@Override
	public void del(T entity) throws Exception {
		T entityPo = useBaseDao().get(entity);
		if (entityPo == null) {
			throw new Exception("要删除的" + entity.getClass().getSimpleName() + "并不存在！");
		}
		useBaseDao().delete(entityPo);
	}

	@Override
	public T save(T entity) throws Exception {
		return save(entity, getPropertyList());
	}

	@Override
	public T save(T entity, String propertyList) throws Exception {
		T entityPo = useBaseDao().save(entity, propertyList);
		return entityPo;
	}

	public void setEntityPk(T entity, PK pk) {
		if (entity!=null){
			try {
				PropertyUtils.setProperty(entity, getIdName(), pk);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@SuppressWarnings("unchecked")
	public PK getEntityPk(T entity) {
		PK id = null;
		
		if (entity!=null){
			try {
				id = (PK)PropertyUtils.getProperty(entity, getIdName());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return id;
	}

	@Override
	public T update(T entity, String propertyList) throws Exception {
		T entityPo = useBaseDao().update(entity, propertyList);
		return entityPo;
	}

	@Override
	public Page<T> manage(Page<T> page) throws Exception {
		// 区别对待实体对象和非实体对象
		if (getBaseDao()!=null&&getBaseDao().isEntity(useBaseDao().getEntityClass())){
			// 是实体对象，检查处理要求的属性列表，单独处理非持久化属性及非直接属性
			page = useBaseDao().find(page);
		}else{
		    // 非实体对象，获取实体列表，开发环境用
			IBaseDao<?,?> dao = null;
			for(Entry<String, IBaseDao<?, ?>> entry:daoMap.entrySet()){
				dao = entry.getValue();
				break;
			}
			if (dao!=null){
				
				page.getData().clear();
				List<Map<String, Object>> list = getEntityNameList();
				int count = list.size();
				page.setTotalCount(new Long(count));
				for(int i=0; i<list.size(); i++){
					if (i>page.getStartIndex()){
						page.getData().add((T)list.get(i));
					}
					if (page.getData().size()>=page.getPageSize()){
						break;
					}
				}
				page.getCondition().put(IBaseDao.PROPERTY_LIST, "id,name");
			}
		}
		return page;
	}
	
	@Override
	public List<T> getAll(String orderBy, long... firstAndMaxResults) throws Exception{
		List<T> list;
		
		list = useBaseDao().findAll(orderBy, firstAndMaxResults);
		
		return list;
	}
	
	@Override
	public List<T> findByExample(T entity, String propertyList, String orderBy, long... firstAndMaxResults) throws Exception{
		List<T> list;
		
		list = useBaseDao().findByExample(entity, propertyList, orderBy, firstAndMaxResults);
		
		return list;
	}
	
	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的对象列表
	 * @throws Exception 
	 */
	@Override
	public List<T> findByProperty(String propertyName, Object value, String orderBy, String propertyList, long... firstAndMaxResults) throws Exception {
		List<T> list;
		
		list = useBaseDao().findByProperty(propertyName, value, orderBy, propertyList, firstAndMaxResults);
		
		return list;
	}
	
	@Override
	public boolean isUnique(T instance, String propertyList) {
		boolean isUnique = false;
		isUnique = this.getBaseDao().isUnique(instance, propertyList);		
		return isUnique;
	}
	
	/**
	 * 获得持久化实体名列表
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getEntityNameList(){
		List<Map<String, Object>> list = null;
		
		try {
			list = useBaseDao().getEntityNameList();
		} catch (Exception e) {
			list = new  ArrayList<Map<String,Object>>();
		}
		
		return list;
	}
	
	@Override
	public String getIdName() {
		String idName = null;
		try {
			if (useBaseDao().isEntity(useBaseDao().getEntityClass())){
				idName = useBaseDao().getPKName();
			}else{
				idName="id";
			}
		} catch (Exception e) {
			idName = null;
		}
		return idName;
	}
	
	/**
     * 获得指定对象在指定查询条件下的位置序号，0算起
     * @param entity
     * @param criteria
     * @param orderBy
     * @return
     */
    public long getIndex(T focus, Page<T> page){
    	return getBaseDao().getIndex(focus, page);
    }

}
